/*
 * MotorBusqueda.cpp
 *
 *  Created on: 13/11/2011
 *      Author: agustin
 */

#include "MotorBusqueda.h"

MotorBusqueda::MotorBusqueda() {
	this->arbol = new ArbolB;
	this->sWords = new Stopwords();
	//this->arbol->print();
}

Lista<reg_rank>* MotorBusqueda::buscar(string query) {
	set<reg_set_docs, classcomp> setDocs;
	stringstream ss;
	ss << query;
	Lista<super_reg*>* listaSReg = new Lista<super_reg*>;
	Lista<reg_rank>* retList = new Lista<reg_rank>;

	Documentos docs;
	float N = docs.getCantDocs();

//	cout << "Query: " << query << endl;

	while (!ss.eof()) {
		string termino;
		ss >> termino;
		//Pasar a lower case
		for (int i = 0; i < termino.length(); i++) {
			termino[i] = tolower(termino[i]);
		}

		//Verifico las stopwords
		if (!this->sWords->isStopword(termino)) {
			super_reg* reg = arbol->buscar(termino);
			if (reg != NULL) {
				listaSReg->agregar(reg);
			}
		}
	}

	//frecuencia de documentos
	int fd = 0;

	IteradorLista<super_reg*> itList = listaSReg->iterador();
	while (itList.tieneSiguiente()) {
		super_reg* reg = itList.siguiente();
		fd = reg->lista->size();
		IteradorLista<reg_docs_variable_t*> itPunteros = reg->lista->iterador();
		while (itPunteros.tieneSiguiente()) {
			reg_docs_variable* regDoc = itPunteros.siguiente();
			reg_set_docs regSet;
			regSet.docId = regDoc->doc_id;

			//busco el puntaje en el set
			if (setDocs.find(regSet) != setDocs.end()) {
				//traigo el documento con su puntaje
				regSet = *setDocs.find(regSet);
			} else {
				//tengo q insertar el nuevo doc al set
				regSet.puntaje = 0;
				setDocs.insert(regSet);
			}
			float log = log10(N / fd);

			float wQj = 1 * log; //Peso del termino j en la Query
			float wij = regDoc->frec * log; //Peso del termino j en ek doc i
			regSet.puntaje += wQj * wij; //La sumatoria

			//actualizo los puntajes en el set
			setDocs.erase(regSet); //Lo borro
			setDocs.insert(regSet); //Lo agrego actualizado
		}
		ArbolB::deleteSuperReg(reg);
	}

	delete listaSReg;

	//Normalizo y Ordeno por puntaje
	set<reg_set_docs, classcomp>::iterator it;
	set<reg_set_docs, classcomp_puntaje> setPuntaje;
	for (it = setDocs.begin(); it != setDocs.end(); it++) {
		size_t di = docs.getCantTerminos((*it).docId);
		reg_set_docs reg;
		reg = *it;
		reg.puntaje = reg.puntaje / di;
		setPuntaje.insert(reg);
	}

	//Graba la lista de documentos en orden de rank ascendente y la devuelve
	set<reg_set_docs, classcomp_puntaje>::reverse_iterator itPnt;
	int rank = 1;
	for (itPnt = setPuntaje.rbegin(); itPnt != setPuntaje.rend(); itPnt++) {
		reg_rank regRnk;
		regRnk.documento = (*itPnt).docId;
		regRnk.rank = rank;
		retList->agregar(regRnk);
		rank++;
	}
	/*
	 IteradorLista<reg_rank> itRank = retList->iterador();
	 while(itRank.tieneSiguiente()){
	 reg_rank rank = itRank.siguiente();
	 cout << rank.rank << " " << docs.getPath(rank.documento) << endl;
	 }
	 */
	return retList;
}

MotorBusqueda::~MotorBusqueda() {
	delete arbol;
	delete sWords;
}

